home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / quartz / quartz10.lha / src / presto / atomic_int.h < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  4.9 KB  |  200 lines

  1. //
  2. // Atomic ints are good for counters, etc...  All integer operations
  3. // on them are defined.
  4. //
  5. // Modification History:
  6. //
  7. // 14-Jan-1989  JEF
  8. // Added 'value' member function to both classes.
  9. //
  10. // 04-Jan-1989  JEF
  11. // Include lock/unlock pair around operator INT in both classes.
  12. //
  13. // 28-Dec-1989  JEF
  14. // Add class HC_AtomicInt.  This new version of an atomic integer utilizes
  15. // the HC_Spinlock, providing faster atomic integer operations when there is
  16. // high contention for the atomic integer.
  17. //
  18.  
  19.  
  20. //
  21. // Binary op
  22. //
  23. // return the value at the time of the lock acquisition
  24. //
  25. #define AIOP(op)\
  26.     inline int operator/**/op/**/(int x)    \
  27.     { \
  28.           lock();  register int tmp = ai_val op x;  unlock(); \
  29.           return tmp; \
  30.         }
  31.  
  32. // 
  33. // Unary op
  34. //
  35. #define AIUNOP(op)\
  36.     inline int operator/**/op/**/()    \
  37.     { \
  38.           lock();  register int tmp = ai_val/**/op; unlock(); \
  39.           return tmp; \
  40.         }
  41.  
  42.  
  43. //
  44. //  Original atomic integer class.
  45. //
  46. class AtomicInt    {
  47.     Spinlock    ai_lock;
  48.     int         ai_val;
  49. public:
  50.     AtomicInt()
  51.         { ai_val = 0; }
  52.     AtomicInt(int x)
  53.         { ai_val = x; }
  54.     AtomicInt(AtomicInt& x)        // should we lock x?
  55.         { ai_val = x.ai_val;}
  56.     ~AtomicInt()
  57.         { unlock(); }
  58.     operator int()
  59.         { lock();   register int tmp = ai_val;   unlock();
  60.           return tmp; }
  61.     void lock()             // Careful.... 
  62.         { ai_lock.lock(); }
  63.     void unlock()
  64.         { ai_lock.unlock(); }
  65.     int&    val()            // use at your own risk
  66.         { return ai_val; }
  67.     int    value()                 // retrieve current value safely
  68.         { lock();   register int tmp = ai_val;   unlock();
  69.           return tmp; }
  70.     AIOP(=)
  71.     AIOP(+=)
  72.     AIOP(*=)
  73.     AIOP(/=)    
  74.     AIOP(%=)
  75.     AIOP(^=)
  76.     AIOP(&=)
  77.     AIOP(|=)
  78.     AIOP(<<=)
  79.     AIOP(>>=)
  80.     AIUNOP(++)        /* pre inc only */
  81.     AIUNOP(--)        /* post inc only */
  82.     int    preinc()
  83.         { lock();   register int tmp = ++ai_val;   unlock();
  84.           return tmp; }
  85.     int    postinc()
  86.         { lock();   register int tmp = ai_val++;   unlock();
  87.           return tmp; }
  88.     int    predec()
  89.         { lock();   register int tmp = --ai_val;   unlock();
  90.           return tmp; }
  91.     int    postdec()
  92.         { lock();   register int tmp = ai_val--;   unlock();
  93.           return tmp; }         
  94.     // Should probably have the rest of the operators here too...
  95. };
  96.  
  97.  
  98. //
  99. //  Atomic integer class specialized for use in high-contention situations.
  100. //
  101. //  The best 'C++' way to do this is probably to make the AtomicInt functions
  102. //  lock and unlock be virtual, and to then derive class HC_AtomicInt from
  103. //  class AtomicInt, providing new lock and unlock functions specific to the
  104. //  HC_Spinlock (as given below).  However, the performance of the member
  105. //  functions of the new derived class is poor compared to the performance
  106. //  realized when a new base class is created (by copying and modifying the
  107. //  original base class).  In the interest of speed, we'll go with the new
  108. //  base class instead of the derived class.
  109. //
  110.  
  111. //
  112. //  The clean (but SLOW) way...  (note - must make ai_val in base class
  113. //  be protected).
  114. //
  115. //class HC_AtomicInt : public AtomicInt    {
  116. //    HC_Spinlock    hc_ai_lock;
  117. //public:
  118. //    HC_AtomicInt ();                         // base class constructor
  119. //    HC_AtomicInt (int x) : (x) {}            //   is called to do
  120. //    HC_AtomicInt (AtomicInt& x) : (x) {}     //   all the work
  121. //
  122. //    ~HC_AtomicInt ()
  123. //        { unlock(); }
  124. //
  125. //    //
  126. //      //  Make base class lock and unlock functions be virtual.  Then
  127. //    //  override them with new versions specific to the high-contention
  128. //      //  spinlock.
  129. //    //
  130. //    void lock ()                             // Careful.... 
  131. //        {
  132. //          hc_ai_lock.lock ();
  133. //                cout << "ai - derived class lock (HC_Spinlock.lock)\n";
  134. //          cout.flush ();
  135. //            }
  136. //
  137. //    void unlock ()
  138. //        {
  139. //              cout << "ai - derived class unlock (HC_Spinlock.unlock)\n";
  140. //                cout.flush ();
  141. //                hc_ai_lock.unlock();
  142. //            }
  143. //};
  144.  
  145.  
  146. //
  147. //  The fast way...
  148. //
  149. class HC_AtomicInt    {
  150.     HC_Spinlock    ai_lock;
  151.     int         ai_val;
  152. public:
  153.     HC_AtomicInt()
  154.         { ai_val = 0; }
  155.     HC_AtomicInt(int x)
  156.         { ai_val = x; }
  157.     HC_AtomicInt(HC_AtomicInt& x)        // should we lock x?
  158.         { ai_val = x.ai_val;}
  159.     ~HC_AtomicInt()
  160.         { unlock(); }
  161.     operator int()
  162.         { lock();   register int tmp = ai_val;   unlock();
  163.           return tmp; }
  164.     void lock()             // Careful.... 
  165.         { ai_lock.lock(); }
  166.     void unlock()
  167.         { ai_lock.unlock(); }
  168.     int&    val()            // use at your own risk
  169.         { return ai_val; }
  170.     int    value()                 // retrieve current value safely
  171.         { lock();   register int tmp = ai_val;   unlock();
  172.           return tmp; }
  173.     AIOP(=)
  174.     AIOP(+=)
  175.     AIOP(*=)
  176.     AIOP(/=)    
  177.     AIOP(%=)
  178.     AIOP(^=)
  179.     AIOP(&=)
  180.     AIOP(|=)
  181.     AIOP(<<=)
  182.     AIOP(>>=)
  183.     AIUNOP(++)        /* pre inc only */
  184.     AIUNOP(--)        /* post inc only */
  185.     int    preinc()
  186.         { lock();   register int tmp = ++ai_val;   unlock();
  187.           return tmp; }
  188.     int    postinc()
  189.         { lock();   register int tmp = ai_val++;   unlock();
  190.           return tmp; }
  191.     int    predec()
  192.         { lock();   register int tmp = --ai_val;   unlock();
  193.           return tmp; }
  194.     int    postdec()
  195.         { lock();   register int tmp = ai_val--;   unlock();
  196.           return tmp; }         
  197.     // Should probably have the rest of the operators here too...
  198. };
  199.  
  200.